package com.lvt.example.thinking.in.spring.questions.L22.web.example02.header;

import org.springframework.http.HttpHeaders;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * desc：class
 *
 * @author LT
 * @date 2022/10/24
 */
@RestController
public class HeaderController {


    @RequestMapping(path = "/hi", method = RequestMethod.GET)
    public String hi(@RequestHeader("myHeaderName") String name) {
        return name;
    }

    /**
     * 案例 1：接受 Header 使用错 Map 类型
     * <p>
     * AbstractNamedValueMethodArgumentResolver
     * -RequestHeaderMethodArgumentResolver
     * -RequestHeaderMapMethodArgumentResolver
     * <p>
     * //方式 1
     *
     * @RequestHeader() MultiValueMap map
     * //方式 2
     * @RequestHeader() HttpHeaders map
     */
    @RequestMapping(path = "/hi1", method = RequestMethod.GET)
    public String hi1(@RequestHeader() Map map) {
        return map.toString();
    }

    @RequestMapping(path = "/hi1/fix1", method = RequestMethod.GET)
    public String hi1fix1(@RequestHeader() MultiValueMap map) {
        return map.toString();
    }

    @RequestMapping(path = "/hi1/fix2", method = RequestMethod.GET)
    public String hi1fix2(@RequestHeader() HttpHeaders map) {
        return map.toString();
    }

    /**
     * 案例 2：错认为 Header 名称首字母可以一直忽略大小写
     */

    @RequestMapping(path = "/hi2", method = RequestMethod.GET)
    public String hi2(@RequestHeader("MyHeader") String myHeader) {
        return myHeader;
    }

    /**
     * 接获取 Header 是可以忽略大小写的，但是如果从接收过来的 Map 中获取 Header 是不能忽略大小写的。
     * <p>
     * RequestHeaderMethodArgumentResolver#resolveName
     */
    @RequestMapping(path = "/hi2", method = RequestMethod.GET)
    public String hi2(@RequestHeader("MyHeader") String myHeader, @RequestHeader MultiValueMap map) {
        //myheadervalue compare with : null
        return myHeader + " compare with : " + map.get("MyHeader");
    }


    @RequestMapping(path = "/hi2/fix1", method = RequestMethod.GET)
    public String hi2fix1(@RequestHeader("MyHeader") String myHeader, @RequestHeader MultiValueMap map) {
        return myHeader + " compare with : " + map.get("myHeader");
    }


    @RequestMapping(path = "/hi2/fix2", method = RequestMethod.GET)
    public String hi2fix2(@RequestHeader("MyHeader") String myHeader, @RequestHeader HttpHeaders map) {
        return myHeader + " compare with : " + map.get("MyHeader");
    }

    /**
     * 案例 3：试图在 Controller 中随意自定义 CONTENT_TYPE 等
     * <p>
     * RequestResponseBodyMethodProcessor#handleReturnValue
     * <p>
     * 们在 Controller 设置了 Content-Type，但是它是一种特殊的 Header，所以在 Spring Boot 基于内嵌 Tomcat 开发时并不一定能设置成功，
     * 最终返回的 Content-Type 是根据实际的返回值及类型等多个因素来决定的。
     * <p>
     * 1. 修改请求中的 Accept 头，约束返回类型,即带上 Accept 头，这样服务器在最终决定 MediaType 时，会选择 Accept 的值。
     * 具体执行可参考方法 AbstractMessageConverterMethodProcessor#getAcceptableMediaTypes。
     * GET http://localhost:8080/hi3
     * Accept:application/json
     * <p>
     * 2.标记返回类型,即使用 produces 属性来指明即可。这样的方式影响的是可以返回的 Media 类型，一旦设置，下面的方法就可以只返回一个指明的类型了。
     * 参考 AbstractMessageConverterMethodProcessor#getProducibleMediaTypes：
     *
     * @RequestMapping(path = "/hi3", method = RequestMethod.GET, produces = {"application/json"})
     */
    @RequestMapping(path = "/hi3", method = RequestMethod.GET)
    public String hi3(HttpServletResponse httpServletResponse) {
        httpServletResponse.addHeader("myheader", "myheadervalue");
        httpServletResponse.addHeader(HttpHeaders.CONTENT_TYPE, "application/json");
        return "ok";
    }
}
